from joblib import Parallel, delayed  
import multiprocessing
from numpy import arange
from datetime import datetime
from lisn_utils import TECData, GPSDateTime, open_file, AttrDict, RNXData

#cat = cat_files('/data/lbo__110106.s4', ['/data/lbo__110106.s4.gz'], GPSDateTime(2011,1,6), 1, 'txt', 'txt', gz=True)
#print cat

class Data():
    TYPE = ''

    def __len__(self):
        return len(self.data)

    def __str__(self):
        '''
        '''
        return '%sData[site=%s, records=%s]' % (self.TYPE, self.station['code'], len(self))
    
    def __getitem__(self, key):
        '''
        '''
        if isinstance(key, int):
            return self.data[self.dates[key]]
        elif isinstance(key, GPSDateTime):
            return self.data[key]
    
    def get_records(self):
        '''
        '''
        return [self.data[dt] for dt in self.dates]

class TECData(Data):
    '''
    '''
    
    TYPE = 'TEC'
    
    def __init__(self, filename, satsystem='G'):
        header = {}
        station = {}
        self.phasearcs = {}
        self.prns = set()
        self.data = {}
        self.satsystem = None
        self.rec_bias = 0
        self.bad_prn = []    
        self.fo = open_file(filename)
        station['fullname'] = self.fo.next().strip()
        station['location'] = tuple(self.fo.values(fmt=float)[:3])
        station['receiver'] = self.fo.next().strip()
        header['receivertype'] = station['receiver']
        header['marker'] = {0: filename.split('/')[-1][:4]}
        station['lisn_code'] = header['marker'][0]
        station['code'] = header['marker'][0]
        self.fo.next()
        self.date = GPSDateTime(*self.fo.values(fmt=int))
        
        while True:
            try:
                vals = self.fo.values()
            except StopIteration:
                break
            if 'PRN' in vals:
                prn = '%s%02d' % (satsystem, int(vals[1]))
                self.prns.add(prn)
                continue
            self.add(prn, vals)
        
        #self.reset([self.dum[dt] for dt in dates])
        self.header = header
        self.station = station
        self.dates = self.data.keys()
        self.dates.sort()
        self.intervals = set([self.dates[i]-self.dates[i-1] for i in range(1, len(self.dates))])
        self.interval = min(self.intervals)
        #[self.checkbreak(i) for i in range(len(self))]
        #self.endphase(len(self)-1, self.prns)    
        
    def add(self, prn, vals):
        '''
        '''
        dt = self.date.replace(hour=int(vals[2]), minute=int(vals[3]), second=int(vals[4]))
        
        if dt not in self.data:
            self.data[dt] = TECrecord(dt, prn, vals)
        else:
            self.data[dt].update(TECrecord(dt, prn, vals))
        
    def checkbreak(self, n):
        '''
        '''
        
        for prn in set(self[n]).union(self.phasearcs):
            if n>0:
                if self[n].epoch-self[n-1].epoch>1800:
                    self.breakphase(n, prn)
                    continue
            
            bad = prn not in self[n] 
                                    
            if not bad and prn not in self.phasearcs:
                self.phasearcs[prn] = [[n, None]]
                continue
            if not bad and self.phasearcs[prn][-1][1] is not None:
                self.phasearcs[prn] += [[n, None]]
                continue
            if prn not in self.phasearcs or self.phasearcs[prn][-1][1] is not \
                    None:
                continue
            if bad:
                self.endphase(n, prn)
                continue
            
    def breakphase(self, n, prn):
        '''
        Begin new phase-connected-arc for satellite prn.
        '''
        if isinstance(prn, (list, tuple, set, dict)):
            [self.breakphase(p) for p in prn]
        elif prn not in self.phasearcs:
            self.phasearcs[prn] = [[n, None]]
        elif prn not in self[n]:
            self.endphase(n, prn)
        else:
            self.endphase(n, prn)
            self.phasearcs[prn] += [[n, None]] 
            
    def endphase(self, n, prn):
        '''
        End current phase-connected-arc, if any, for satellite prn.
        Ends arc just before the current record.
        '''

        if isinstance(prn, (list, tuple, set, dict)):
            [self.endphase(n, p) for p in prn]
        elif prn in self.phasearcs and self.phasearcs[prn][-1][1] is None:
            self.phasearcs[prn][-1][1] = n-1          
                
class TECrecord(AttrDict):
    '''
    '''
    
    KEYS = ['eqTEC', 'ltime', 'ele', 'lat', 'lon', 'sTEC', 'azi']
    
    def __init__(self, epoch, prn, vals):
        self.epoch = epoch
        self[prn] = dict(zip(self.KEYS, [float(x) for x in vals[5:]]))    


dt = GPSDateTime()
tec = TECData('/data/lanc_150210.dat.gz')
print tec[100]

print (GPSDateTime()-dt)